﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Configuration;

namespace Ogdi.Data.DataLoader
{
    public class DataLoader : IDataLoader
    {        
        public DataLoader(DataLoaderParams parameters, EntityProducer producer, EntityProcessor processor)
        {
            Params = parameters;
            Producer = producer;
            Processor = processor;
        }

        protected DataLoaderParams Params { get; set; }

        protected EntityProducer Producer { get; set; }

        protected EntityProcessor Processor { get; set; }

        public virtual void Load(ProgressCallback progressNotifier, OnContinueExceptionCallback exceptionNotifier)
        {
            Producer.ValidateParams();
            Processor.ValidateParams(Producer.SchemaEntity);

            OnLoadStart();            
            int count = 0;

            int loadThreadsCount = int.Parse(ConfigurationSettings.AppSettings["LoadThreadsCount"]);                                   

            ParallelOptions options = new ParallelOptions(){ MaxDegreeOfParallelism = loadThreadsCount};            

            Parallel.ForEach(this.Producer.GetEntitiesEnumerator(exceptionNotifier),options, i =>
            {                
                try
                {
                    Processor.ProcessEntity(Params.TableMetadataEntity.EntitySet, i);

                }
                catch (Exception ex)
                {
                    if (exceptionNotifier != null)
                    {
                        exceptionNotifier(new EntityProcessingException(i.ToString(),ex));
                    }
                }


                if (progressNotifier != null)
                {
                    progressNotifier(Producer.EntityCount, Interlocked.Increment(ref count));
                }
            }
            );
                       
            Processor.ProcessTableMetadataEntity(DataLoaderConstants.EntitySetTableMetadata, Params.TableMetadataEntity);
            Processor.ProcessEntityMetadataEntity(DataLoaderConstants.EntitySetEntityMetadata, Producer.SchemaEntity);            
        }
        
        protected virtual void OnLoadStart() 
        { 
        }

    }
}
